/**
 * 
 */
package com.delta.rafg.core.database.impl;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import com.delta.rafg.core.config.ConfigSettings;
import com.delta.rafg.core.database.DataHandlerOptions;
import com.delta.rafg.core.database.IDataHandler;
import com.delta.rafg.core.database.IGenericDataSource;
import com.delta.rafg.core.database.impl.ACacheDataHandler.CacheTableColumnInfo;
import com.delta.rafg.core.database.impl.AGenericDataSource.GenericDataSourceColumnInfo;
import com.delta.rafg.core.database.impl.util.DatabaseUtils;
import com.delta.rafg.core.exception.RAFGException;

/**
 * @author D9127520
 *
 */
public class GenericDataHandlerImpl extends ADataHandler implements IDataHandler {

	/**
	 * 
	 */
	private static final long serialVersionUID = -6493835889796559122L;
	
	public static final String CACHE_HANDLER_KEY = "CACHE_HANDLER_KEY";
	
	private IGenericDataSource genericDataSource;
	private Connection conn;
	private ACacheDataHandler cacheDataSource;

	private String pollFrequency = "01:00:00"; //1am
	private POLL_STYLE pollStyle = POLL_STYLE.TIMESTAMP;

	
	public GenericDataHandlerImpl(IGenericDataSource datasource) {
		super.pollFrequency = pollFrequency;
		super.pollStyle = pollStyle;
		genericDataSource = datasource;
		conn = datasource.getSqlConnection();
	}
	
	/* (non-Javadoc)
	 * @see com.delta.rafg.core.database.IDataHandler#closeConnection()
	 */
	@Override
	public void closeConnection() {
	}

	/* (non-Javadoc)
	 * @see com.delta.rafg.core.database.IDataHandler#destroy()
	 */
	@Override
	public void destroy() {
	}

	/* (non-Javadoc)
	 * @see com.delta.rafg.core.database.IDataHandler#getChangedTables()
	 */
	@Override
	public String[] getChangedTables() throws RAFGException {
		return genericDataSource.getChangedTables();
	}

	/* (non-Javadoc)
	 * @see com.delta.rafg.core.database.IDataHandler#getConnection()
	 */
	@Override
	public Connection getConnection() throws RAFGException {
		return conn;
	}

	/* (non-Javadoc)
	 * @see com.delta.rafg.core.database.IDataHandler#getDataHandlerOptions()
	 */
/*	
	@Override
	public DataHandlerOptions getDataHandlerOptions() {
		return null;
	}
*/
	/* (non-Javadoc)
	 * @see com.delta.rafg.core.database.IDataHandler#getMonitoredSchemas()
	 */
	@Override
	public String[] getMonitoredSchemas() {
		String schema = genericDataSource.getSchemaName();
		return new String[]{schema};
	}

	/* (non-Javadoc)
	 * @see com.delta.rafg.core.database.IDataHandler#getMonitoredTables()
	 */
	@Override
	public String[] getMonitoredTables() {
		List<String> tables = new ArrayList<String>();
		String schema = genericDataSource.getSchemaName();
		for(String table : genericDataSource.getTableNames()) {
			tables.add(schema + "." + table);
		}
		return tables.toArray(new String[tables.size()]);
	}

	/* (non-Javadoc)
	 * @see com.delta.rafg.core.database.IDataHandler#initialize(com.delta.rafg.core.database.DataHandlerOptions)
	 */
	@Override
	public void initialize(DataHandlerOptions options) throws RAFGException {
		super.initialize(options);
		cacheDataSource = (ACacheDataHandler) options.getDataHandlerSpecificOptionsMap().get(CACHE_HANDLER_KEY);
		if (cacheDataSource != null) {
			validateCache();
		}
	}

	/* (non-Javadoc)
	 * @see com.delta.rafg.core.database.IDataHandler#initialize(java.lang.String)
	 */
	@Override
	public void initialize(String dataHandlerPropertyIdentifier)
			throws RAFGException {
	}

	private void createCache(String tableName) throws RAFGException {
		List<String> indexCols = genericDataSource.getIndexColumns(tableName);
		List<GenericDataSourceColumnInfo> dsColumns = genericDataSource.getColumns(tableName);
		List<CacheTableColumnInfo> columns = new ArrayList<CacheTableColumnInfo>();
		for(GenericDataSourceColumnInfo dsCol : dsColumns) {
			String colName = dsCol.getColumnName();
			int colLen = dsCol.getColumnLen();
			int colType = dsCol.getColumnType();
			int colScale = dsCol.getColumnScale();
			boolean isNullable = dsCol.isNullable();
			boolean isPrimaryKey = (indexCols != null && indexCols.contains(colName)); 
			columns.add(new CacheTableColumnInfo(colName, colType, colLen, colScale, isPrimaryKey, isNullable)); 
		}
		cacheDataSource.createCacheTable(tableName, columns);
	}

	private void validateCache() throws RAFGException {
    	Statement stmt = null;
    	try {
			Connection conn = cacheDataSource.getConnection();
			stmt = conn.createStatement();
			for (String cacheTable : getMonitoredTables()) {
				String schemaName = DatabaseUtils.getSchemaName(cacheTable);
				String tableName = DatabaseUtils.getTableName(cacheTable);
				String fullyQualifiedTableName = schemaName + cacheDataSource.getCacheSchemaSuffix() + "." + tableName;
				
//            	RAFGLogger.info("Inspecting table " + fullyQualifiedTableName);
        		if (!cacheDataSource.checkTableExists(stmt, fullyQualifiedTableName)) {
        			createCache(fullyQualifiedTableName);
        			break;
        		}
			}
		} catch (SQLException e) {
			throw new RAFGException(e);
		} finally {
			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException e) {
				}
			}
		}
	}

	/* (non-Javadoc)
	 * @see com.delta.rafg.core.database.IDataHandler#initialize(java.lang.String, com.delta.rafg.core.database.DataHandlerOptions)
	 */
	@Override
	public void initialize(String dataHandlerPropertyIdentifier,
			DataHandlerOptions options) throws RAFGException {
	}

	/* (non-Javadoc)
	 * @see com.delta.rafg.core.database.IDataHandler#initialize(java.lang.String, com.delta.rafg.core.config.ConfigSettings)
	 */
	@Override
	public void initialize(String dataHandlerPropertyIdentifier,
			ConfigSettings configSettings) throws RAFGException {
	}
}
